//
// Created by nilyang on 2021/11/25.
//

#include "CopyElision.h"
#include <memory>
#include <cstring>

CopyElision func_GetCopyElision_NRVO(const char* str) {
    std::cout << "NRVO 具名返回值优化" << std::endl;
    CopyElision d(str);
    return d;
}
CopyElision func_GetCopyElision_URVO(const char *str) {
    std::cout << "URVO 匿名返回值优化" << std::endl;
    return CopyElision(str);
}

CopyElision::CopyElision(const char* str):
        bucketSize(0),
        bucket(nullptr)
{
    bucketSize = Len(str);
    bucket = new char[bucketSize+1];
    std::memcpy(bucket, str, bucketSize);
    std::cout << "构造函数\n"<<str ;
}

CopyElision::CopyElision(const CopyElision &d) {
    bucketSize = d.bucketSize;
    bucket = new char[bucketSize+1];
    std::memcpy(bucket, d.bucket, bucketSize);
    std::cout << "拷贝构造函数\n" ;
}

CopyElision::~CopyElision() {
    delete[] bucket;
    bucket = nullptr;
    std::cout << "析构函数\n" ;
}

std::size_t CopyElision::Len(const char* str) const {
    std::size_t size = 0;
    const char *pb = str;
    for (; *pb != '\0'; pb++)
        size += 1;
    return size;
}

std::size_t CopyElision::GetLen() const {
    return Len(bucket);
}

void func_cpp_elision() {
    std::cout << "------{start: C++ Copy Elision }-------\n";
    const char* xstr="hello world\n";
    {
        CopyElision d = func_GetCopyElision_NRVO(xstr);
        std::cout << "具名返回值优化：CppCopyElision` d.bucketSize=" << d.GetLen() << "\n";
        std::cout << "具名返回值优化：CppCopyElision` d.Len() = " << d.GetLen() << std::endl;
    }
    {
        CopyElision d2 = func_GetCopyElision_URVO(xstr);
        std::cout << "匿名返回值优化：CppCopyElision` d2.bucketSize=" << d2.GetLen() << "\n";
        std::cout << "匿名返回值优化：CppCopyElision` d2.Len() = " << d2.GetLen() << std::endl;
    }
    std::cout << "------{end: C++ Copy Elision }-------\n";

}